#ifndef CNC_BASE_EXECUTIVE_H
#define CNC_BASE_EXECUTIVE_H

// provided interface
#include "machop.h"
// required interfaces
#include "motctl.h"
#include "globaldata.h"
#include "logicctl.h" 
#include "cmdstream.h"
// basic component model
#include <bcm/bcm.h>

namespace cnc {

	namespace base {

		class Executive : public bcm::Identifier<bcm::Component>,
			public bcm::Identifier<MachineOperation>
		{
			cnc::motion::Control *mc_;
			cnc::plc::LogicControl *lc_;
			cnc::base::GlobalData *gd_;
			cnc::compiler::CommandStream *cs_;
		protected:
			Executive() : bcm::Identifier<bcm::Component>("exec", "Executive"),
				bcm::Identifier<MachineOperation>("machop", "Machine Operation"),
			mc_(0), lc_(0), gd_(0), cs_(0) {}
		protected: // bcm::Component
			virtual bcm::IdentifierData *getProvidedInterfaceTable()
			{
				static bcm::IdentifierData idData[] = {
					{ "machop", "Machine Operation" },
					{ 0, 0 }
				};
				return idData;
			}
			virtual bcm::IdentifierData *getRequiredInterfaceTable()
			{
				static bcm::IdentifierData idData[] = {
					{ "motctl", "Control" },
					{ "gdata", "Global Data"},
					{ "logicctl", "Logic Control"},
					{ 0, 0 }
				};
				return idData;
			}
			virtual bcm::Interface *getInterface(const char *id)
			{
				if (std::string("machop") == id)
					return static_cast<MachineOperation *>(this);
				return 0;
			}
			virtual bool setInterface(Interface *iface)
			{
				if (iface == 0)
					return false;
				if (std::string("motctl") == iface->getID()) {
					cnc::motion::Control *mc = dynamic_cast<cnc::motion::Control *>(iface);
					if (mc == 0)
						return false;
					mc_ = mc;
				} else if (std::string("logicctl") == iface->getID()) {
					cnc::plc::LogicControl *lc = dynamic_cast<cnc::plc::LogicControl *>(iface);
					if (lc == 0)
						return false;
					lc_ = lc;
				} else if (std::string("gdata") == iface->getID()) {
					cnc::base::GlobalData *gd = dynamic_cast<cnc::base::GlobalData *>(iface);
					if (gd == 0)
						return false;
					gd_ = gd;
				} else if (std::string("cmdstream") == iface->getID()) {
					cnc::compiler::CommandStream *cs = dynamic_cast<cnc::compiler::CommandStream *>(iface);
					if (cs == 0)
						return false;
					cs_ = cs;
				} else
					return false;
				return true;
			}
		protected: // Machine Operation
			virtual bool isHome(const int axis = -1)
			{
				return true;
			}
			virtual AxisStatus getAxisStatus(const int axis)
			{
				return AS_HOME;
			}
			virtual void homeAxis(const int axis)
			{
			}
		public:
			static Executive &instance()
			{
				static Executive object;
				return object;
			}
		};

	} // namespace base

} // namespace cnc

#endif
